<template>
  <div class="app-container">
    <a-form :model="queryParams" ref="queryRef" v-show="showSearch" layout="inline">
      <a-form-item label="角色名称" field="roleName">
        <a-input
            size="small"
            v-model="queryParams.roleName"
            placeholder="请输入角色名称"
            clearable
            style="width: 240px"
            @keyup.enter="handleQuery"
        />
      </a-form-item>
      <a-form-item label="权限字符" field="roleKey">
        <a-input
            size="small"
            v-model="queryParams.roleKey"
            placeholder="请输入权限字符"
            clearable
            style="width: 240px"
            @keyup.enter="handleQuery"
        />
      </a-form-item>
      <a-form-item label="状态" field="status">
        <a-select
            size="small"
            v-model="queryParams.status"
            placeholder="角色状态"
            clearable
            style="width: 240px"
        >
          <a-option
              v-for="dict in sys_normal_disable"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"
          />
        </a-select>
      </a-form-item>
      <a-form-item label="创建时间" style="width: 308px">
        <a-range-picker
            size="small"
            v-model="dateRange"
        ></a-range-picker>
      </a-form-item>
      <a-form-item>
        <a-button type="primary" size="small" class="button-margin-right" @click="handleQuery">
          <icon-Search/>
          搜索
        </a-button>
        <a-button size="small" @click="resetQuery">
          <icon-loop/>
          重置
        </a-button>
      </a-form-item>
    </a-form>
    <!--操作-->
    <a-row :gutter="10" class="mb8">
      <a-col :span="1.5">
        <a-button
            size="small"
            type="primary"
            @click="handleAdd"
            v-hasPermi="['system:role:add']"
        >
          <icon-plus/>
          新增
        </a-button>
      </a-col>
      <a-col :span="1.5">
        <a-button
            type="primary"
            status="success"
            size="small"
            :disabled="single"
            @click="handleUpdate"
            v-hasPermi="['system:role:edit']"
        >
          <icon-edit/>
          修改
        </a-button>
      </a-col>
      <a-col :span="1.5">
        <a-button
            type="primary"
            status="danger"
            size="small"
            :disabled="multiple"
            @click="handleDelete"
            v-hasPermi="['system:role:remove']"
        >
          <icon-delete/>
          删除
        </a-button>
      </a-col>
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </a-row>
    <!-- 表格数据 -->
    <a-table v-loading="loading" :data="roleList" row-key="roleId" :row-selection="roleRowSelection"
             v-model:selectedKeys="selectedRoleIds" :pagination="false">
      <template #columns>
        <a-table-column title="角色编号" data-index="roleId" width="120"/>
        <a-table-column title="角色名称" data-index="roleName" :show-overflow-tooltip="true" width="150"/>
        <a-table-column title="权限字符" data-index="roleKey" :show-overflow-tooltip="true" width="150"/>
        <a-table-column title="显示顺序" data-index="roleSort" width="100"/>
        <a-table-column title="状态" align="center" width="100">
          <template #cell="{ record }">
            <a-switch
                v-model="record.status"
                checked-value="0"
                unchecked-value="1"
                @change="handleStatusChange(record)"
            ></a-switch>
          </template>
        </a-table-column>
        <a-table-column title="创建时间" align="center" data-index="createTime">
          <template #cell="{ record }">
            <span>{{ parseTime(record.createTime) }}</span>
          </template>
        </a-table-column>
        <a-table-column title="操作" align="center" class-name="small-padding fixed-width">
          <template #cell="{ record }">
            <a-tooltip content="修改" placement="top" v-if="record.roleId !== 1">
              <a-button
                  class="button-text-padding"
                  type="text"
                  @click="handleUpdate(record)"
                  v-hasPermi="['system:role:edit']"
              >
                <icon-edit/>
              </a-button>
            </a-tooltip>
            <a-tooltip content="删除" placement="top" v-if="record.roleId !== 1">
              <a-button
                  class="button-text-padding"
                  type="text"
                  @click="handleDelete(record)"
                  v-hasPermi="['system:role:remove']"
              >
                <icon-delete/>
              </a-button>
            </a-tooltip>
            <a-tooltip content="数据权限" placement="top" v-if="record.roleId !== 1">
              <a-button
                  class="button-text-padding"
                  type="text"
                  icon="CircleCheck"
                  @click="handleDataScope(record)"
                  v-hasPermi="['system:role:edit']"
              >
                <icon-check-circle/>
              </a-button>
            </a-tooltip>
            <a-tooltip content="分配用户" placement="top" v-if="record.roleId !== 1">
              <a-button
                  class="button-text-padding"
                  type="text"
                  @click="handleAuthUser(record)"
                  v-hasPermi="['system:role:edit']"
              >
                <icon-user/>
              </a-button>
            </a-tooltip>
          </template>
        </a-table-column>
      </template>
    </a-table>

    <pagination
        v-show="total > 0"
        :total="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        @pagination="getList"
    />

    <!-- 添加或修改角色配置对话框 -->
    <a-modal v-model:visible="addOrUpdateDialog" width="500px" title-align="start">
      <template #title>
        {{ title }}
      </template>
      <a-form ref="roleRef" :model="form" :rules="rules" auto-label-width>
        <a-form-item label="角色名称" field="roleName">
          <a-input size="small" v-model="form.roleName" placeholder="请输入角色名称"/>
        </a-form-item>
        <a-form-item prop="roleKey">
          <template #label>
                  <span>
                     <a-tooltip content="控制器中定义的权限字符，如：@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
                        <icon-question-circle-fill/>
                     </a-tooltip>
                     权限字符
                  </span>
          </template>
          <a-input size="small" v-model="form.roleKey" placeholder="请输入权限字符"/>
        </a-form-item>
        <a-form-item label="角色顺序" field="roleSort">
          <a-input-number size="small" v-model="form.roleSort" controls-position="right" :min="0"/>
        </a-form-item>
        <a-form-item label="状态">
          <a-radio-group v-model="form.status" size="small">
            <a-radio
                v-for="dict in sys_normal_disable"
                :key="dict.value"
                :value="dict.value"
            >{{ dict.label }}
            </a-radio>
          </a-radio-group>
        </a-form-item>
        <a-form-item label="菜单权限">
          <a-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</a-checkbox>
          <a-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</a-checkbox>
          <a-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动
          </a-checkbox>
        </a-form-item>
        <a-form-item label="">
          <a-tree
              class="tree-border"
              :data="menuOptions"
              v-model:checked-keys="checkedMenuIds"
              v-model:half-checked-keys="halfCheckedMenuIds"
              checked-strategy="all"
              :checkable="true"
              ref="menuRef"
              :check-strictly="!form.menuCheckStrictly"
              empty-text="加载中，请稍候"
              :fieldNames="{ title: 'label', key: 'id', children: 'children' }"
          ></a-tree>
        </a-form-item>
        <a-form-item label="备注">
          <a-textarea size="small" v-model="form.remark" placeholder="请输入内容"></a-textarea>
        </a-form-item>
      </a-form>
      <template #footer>
        <div class="dialog-footer">
          <a-button type="primary" size="small" class="button-margin-right" @click="submitForm">确 定</a-button>
          <a-button @click="cancel" size="small">取 消</a-button>
        </div>
      </template>
    </a-modal>

    <!-- 分配角色数据权限对话框 -->
    <a-modal v-model:visible="openDataScopeDialog" width="500px" title-align="start">
      <template #title>
        {{ title }}
      </template>
      <a-form :model="form" auto-label-width>
        <a-form-item label="角色名称">
          <a-input size="small" v-model="form.roleName" :disabled="true"/>
        </a-form-item>
        <a-form-item label="权限字符">
          <a-input size="small" v-model="form.roleKey" :disabled="true"/>
        </a-form-item>
        <a-form-item label="权限范围">
          <a-select size="small" v-model="form.dataScope" @change="dataScopeSelectChange">
            <a-option
                v-for="item in dataScopeOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            ></a-option>
          </a-select>
        </a-form-item>
        <a-form-item label="数据权限" v-show="form.dataScope == 2">
          <a-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</a-checkbox>
          <a-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</a-checkbox>
          <a-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动
          </a-checkbox>
        </a-form-item>
        <a-form-item>
          <a-tree
              class="tree-border"
              :data="deptOptions"
              v-model:checked-keys="checkedDeptIds"
              :checkable="true"
              ref="deptRef"
              :check-strictly="!form.deptCheckStrictly"
              empty-text="加载中，请稍候"
              :fieldNames="{ title: 'label', key: 'id', children: 'children' }"
          ></a-tree>
        </a-form-item>
      </a-form>
      <template #footer>
        <div class="dialog-footer">
          <a-button type="primary" size="small" class="button-margin-right" @click="submitDataScope">确 定</a-button>
          <a-button @click="cancelDataScope" size="small">取 消</a-button>
        </div>
      </template>
    </a-modal>
  </div>
</template>

<script setup name="Role">
import {addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole} from "@/api/system/role";
import {roleMenuTreeselect, treeselect as menuTreeselect} from "@/api/system/menu";
import {roleDeptTreeselect} from "@/api/system/dept";
import {useRouter} from "vue-router";
import {computed, getCurrentInstance, nextTick, reactive, ref, toRefs} from "vue";

const router = useRouter();
const {proxy} = getCurrentInstance();
const {sys_normal_disable} = proxy.useDict("sys_normal_disable");

const roleList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const total = ref(0);
const title = ref("");
const dateRange = ref([]);
const menuOptions = ref([]);
const menuExpand = ref(false);
const menuNodeAll = ref(false);
const deptExpand = ref(true);
const deptNodeAll = ref(false);
const deptOptions = ref([]);
const openDataScope = ref(false);
const menuRef = ref(null);
const deptRef = ref(null);
const openDataScopeDialog = ref(false);
const addOrUpdateDialog = ref(false);
const direction = ref('rtl')

/** 数据范围选项*/
const dataScopeOptions = ref([
  {value: "1", label: "全部数据权限"},
  {value: "2", label: "自定数据权限"},
  {value: "3", label: "本部门数据权限"},
  {value: "4", label: "本部门及以下数据权限"},
  {value: "5", label: "仅本人数据权限"}
]);

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    roleName: undefined,
    roleKey: undefined,
    status: undefined
  },
  rules: {
    roleName: [{required: true, message: "角色名称不能为空", trigger: "blur"}],
    roleKey: [{required: true, message: "权限字符不能为空", trigger: "blur"}],
    roleSort: [{required: true, message: "角色顺序不能为空", trigger: "blur"}]
  },
});

const {queryParams, form, rules} = toRefs(data);

/** 查询角色列表 */
function getList() {
  loading.value = true;
  selectedRoleIds.value = []
  listRole(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
    roleList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  dateRange.value = [];
  proxy.resetForm("queryRef");
  handleQuery();
}

/** 删除按钮操作 */
function handleDelete(row) {
  const roleIds = row.roleId || selectedRoleIds.value;
  proxy.$confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(function () {
    return delRole(roleIds);
  }).then(() => {
    getList();
    proxy.$message.success("删除成功");
  }).catch(() => {
  });
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download("system/role/export", {
    ...queryParams.value,
  }, `role_${new Date().getTime()}.xlsx`);
}

/** 开启表格多选  */
const selectedRoleIds = ref([]);
const roleRowSelection = reactive({
  type: 'checkbox',
  showCheckedAll: true,
  onlyCurrent: false,
});
// 修改按钮生效
const single = computed(() => {
  return selectedRoleIds.value.length !== 1
});
// 删除按钮生效
const multiple = computed(() => {
  return !selectedRoleIds.value.length
});

/** 角色状态修改 */
function handleStatusChange(row) {
  let text = row.status === "0" ? "启用" : "停用";
  proxy.$confirm('确认要"' + text + '""' + row.roleName + '"角色吗?').then(function () {
    return changeRoleStatus(row.roleId, row.status);
  }).then(() => {
    proxy.$message.success(text + "成功");
  }).catch(function () {
    row.status = row.status === "0" ? "1" : "0";
  });
}

/** 更多操作 */
function handleCommand(command, row) {
  switch (command) {
    case "handleDataScope":
      handleDataScope(row);
      break;
    case "handleAuthUser":
      handleAuthUser(row);
      break;
    default:
      break;
  }
}

/** 分配用户 */
function handleAuthUser(row) {
  router.push("/system/role-auth/user/" + row.roleId);
}

/** 查询菜单树结构 */
function getMenuTreeselect() {
  menuTreeselect().then(response => {
    menuOptions.value = response.data;
  });
}

/** 所有部门节点数据 */
function getDeptAllCheckedKeys() {
  // 目前被选中的部门节点
  let checkedKeys = deptRef.value.getCheckedKeys();
  // 半选中的部门节点
  let halfCheckedKeys = deptRef.value.getHalfCheckedKeys();
  checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
  return checkedKeys;
}

/** 重置新增的表单以及其他数据  */
function reset() {
  if (menuRef.value != undefined) {
    checkedMenuIds.value = [];
  }
  menuExpand.value = false;
  menuNodeAll.value = false;
  deptExpand.value = true;
  deptNodeAll.value = false;
  form.value = {
    roleId: undefined,
    roleName: undefined,
    roleKey: undefined,
    roleSort: 0,
    status: "0",
    menuIds: [],
    deptIds: [],
    menuCheckStrictly: true,
    deptCheckStrictly: true,
    remark: undefined
  };
  proxy.resetForm("roleRef");
}

/** 添加角色 */
function handleAdd() {
  reset();
  getMenuTreeselect();
  addOrUpdateDialog.value = true;
  title.value = "添加角色";
}

/** 修改角色 */
function handleUpdate(row) {
  reset();
  const roleId = row.roleId || selectedRoleIds.value[0];
  const roleMenu = getRoleMenuTreeselect(roleId);
  getRole(roleId).then(response => {
    form.value = response.data;
    form.value.roleSort = Number(form.value.roleSort);
    addOrUpdateDialog.value = true;
    nextTick(() => {
      roleMenu.then((res) => {
        let checkedKeys = res.checkedKeys;
        menuRef.value.checkNode(checkedKeys, true, false);
      });
    });
    title.value = "修改角色";
  });
}

/** 根据角色ID查询菜单树结构 */
function getRoleMenuTreeselect(roleId) {
  return roleMenuTreeselect(roleId).then(response => {
    menuOptions.value = response.menus;
    return response;
  });
}

/** 根据角色ID查询部门树结构 */
function getRoleDeptTreeselect(roleId) {
  return roleDeptTreeselect(roleId).then(response => {
    deptOptions.value = response.depts;
    return response;
  });
}

/** 树权限（展开/折叠）*/
function handleCheckedTreeExpand(value, type) {
  if (type == "menu") {
    menuRef.value.expandAll(value)
  } else if (type == "dept") {
    deptRef.value.expandAll(value)
  }
}

/** 树权限（全选/全不选） */
function handleCheckedTreeNodeAll(value, type) {
  if (type == "menu") {
    menuRef.value.checkAll(value);
  } else if (type == "dept") {
    deptRef.value.checkAll(value);
  }
}

/** 树权限（父子联动） */
function handleCheckedTreeConnect(value, type) {
  if (type == "menu") {
    form.value.menuCheckStrictly = value ? true : false;
  } else if (type == "dept") {
    form.value.deptCheckStrictly = value ? true : false;
  }
}

/** 所有菜单节点数据 */
const checkedMenuIds = ref([]);
// 半选中的节点
const halfCheckedMenuIds = ref([])

// 所有菜单节点数据
function getMenuAllCheckedKeys() {
  // 目前被选中的菜单节点
  let checkedKeys = menuRef.value.getCheckedNodes('all');
  // 半选中的菜单节点
  let halfCheckedKeys = menuRef.value.getHalfCheckedNodes();
  console.log(checkedKeys, checkedKeys)
  // checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
  // return checkedKeys;
};

/** 提交按钮 */
function submitForm() {
  console.log(checkedMenuIds.value, halfCheckedMenuIds.value)
  proxy.$refs["roleRef"].validate(valid => {
    if (!valid) {
      if (form.value.roleId != undefined) {
        form.value.menuIds = [...checkedMenuIds.value, ...halfCheckedMenuIds.value];
        updateRole(form.value).then(response => {
          proxy.$message.success("修改成功");
          addOrUpdateDialog.value = false;
          getList();
        });
      } else {
        form.value.menuIds = checkedMenuIds.value;
        addRole(form.value).then(response => {
          proxy.$message.success("新增成功");
          addOrUpdateDialog.value = false;
          getList();
        });
      }
    }
  });
}

/** 取消按钮 */
function cancel() {
  addOrUpdateDialog.value = false;
  reset();
}

/** 选择角色权限范围触发 */
function dataScopeSelectChange(value) {
  if (value !== "2") {
    checkedDeptIds.value = []
  }
}

// 数据权限选择的部门
const checkedDeptIds = ref([])

/** 分配数据权限操作 */
function handleDataScope(row) {
  reset();
  const roleDeptTreeselect = getRoleDeptTreeselect(row.roleId);
  getRole(row.roleId).then(response => {
    form.value = response.data;
    openDataScopeDialog.value = true;
    nextTick(() => {
      roleDeptTreeselect.then(res => {
        console.log(res.checkedKeys)
        nextTick(() => {
          if (deptRef.value) {
            deptRef.value.checkNode(res.checkedKeys, true, false);
          }
        });
      });
    });
    title.value = "分配数据权限";
  });
}

/** 提交按钮（数据权限） */
function submitDataScope() {
  if (form.value.roleId != undefined) {
    form.value.deptIds = checkedDeptIds.value
    dataScope(form.value).then(response => {
      proxy.$message.success("修改成功");
      openDataScopeDialog.value = false;
      getList();
    });
  }
}

/** 取消按钮（数据权限）*/
function cancelDataScope() {
  openDataScopeDialog.value = false;
  reset();
}

getList();
</script>
<style scoped>
.tree-border {
  margin-top: 5px;
  border: 1px solid #e5e6e7;
  background: #ffffff;
  border-radius: 4px;
  height: 200px;
  overflow: auto;
}
</style>
